//! 通用数据模型
//! 
//! 定义所有产品线共用的数据结构

use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};

/// Binance API错误响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BinanceApiError {
    pub code: i32,
    pub msg: String,
}

/// 服务器时间
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerTime {
    #[serde(rename = "serverTime")]
    pub server_time: u64,
}

impl std::fmt::Display for ServerTime {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.server_time)
    }
}

/// 订单状态
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum OrderStatus {
    #[serde(rename = "NEW")]
    New,
    #[serde(rename = "PARTIALLY_FILLED")]
    PartiallyFilled,
    #[serde(rename = "FILLED")]
    Filled,
    #[serde(rename = "CANCELED")]
    Canceled,
    #[serde(rename = "PENDING_CANCEL")]
    PendingCancel,
    #[serde(rename = "REJECTED")]
    Rejected,
    #[serde(rename = "EXPIRED")]
    Expired,
}

/// 订单方向
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum OrderSide {
    #[serde(rename = "BUY")]
    Buy,
    #[serde(rename = "SELL")]
    Sell,
}

/// 订单类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum OrderType {
    #[serde(rename = "LIMIT")]
    Limit,
    #[serde(rename = "MARKET")]
    Market,
    #[serde(rename = "STOP_LOSS")]
    StopLoss,
    #[serde(rename = "STOP_LOSS_LIMIT")]
    StopLossLimit,
    #[serde(rename = "TAKE_PROFIT")]
    TakeProfit,
    #[serde(rename = "TAKE_PROFIT_LIMIT")]
    TakeProfitLimit,
    #[serde(rename = "LIMIT_MAKER")]
    LimitMaker,
}

/// 订单有效期
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TimeInForce {
    #[serde(rename = "GTC")]
    Gtc,
    #[serde(rename = "IOC")]
    Ioc,
    #[serde(rename = "FOK")]
    Fok,
    #[serde(rename = "GTX")]
    Gtx,
}

/// 订单响应类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum OrderResponseType {
    #[serde(rename = "ACK")]
    Ack,
    #[serde(rename = "RESULT")]
    Result,
    #[serde(rename = "FULL")]
    Full,
}

/// 执行类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ExecutionType {
    #[serde(rename = "NEW")]
    New,
    #[serde(rename = "CANCELED")]
    Canceled,
    #[serde(rename = "REPLACED")]
    Replaced,
    #[serde(rename = "REJECTED")]
    Rejected,
    #[serde(rename = "TRADE")]
    Trade,
    #[serde(rename = "EXPIRED")]
    Expired,
}

/// 交易方向
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TradeSide {
    #[serde(rename = "BUY")]
    Buy,
    #[serde(rename = "SELL")]
    Sell,
}

/// 交易者类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TradeType {
    #[serde(rename = "MAKER")]
    Maker,
    #[serde(rename = "TAKER")]
    Taker,
}

/// 工作类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum WorkingType {
    #[serde(rename = "MARK_PRICE")]
    MarkPrice,
    #[serde(rename = "CONTRACT_PRICE")]
    ContractPrice,
}

/// 持仓方向
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum PositionSide {
    #[serde(rename = "BOTH")]
    Both,
    #[serde(rename = "LONG")]
    Long,
    #[serde(rename = "SHORT")]
    Short,
}

/// 订单方向（字符串版本，用于API调用）
impl ToString for OrderSide {
    fn to_string(&self) -> String {
        match self {
            OrderSide::Buy => "BUY".to_string(),
            OrderSide::Sell => "SELL".to_string(),
        }
    }
}

/// 订单类型（字符串版本，用于API调用）
impl ToString for OrderType {
    fn to_string(&self) -> String {
        match self {
            OrderType::Limit => "LIMIT".to_string(),
            OrderType::Market => "MARKET".to_string(),
            OrderType::StopLoss => "STOP_LOSS".to_string(),
            OrderType::StopLossLimit => "STOP_LOSS_LIMIT".to_string(),
            OrderType::TakeProfit => "TAKE_PROFIT".to_string(),
            OrderType::TakeProfitLimit => "TAKE_PROFIT_LIMIT".to_string(),
            OrderType::LimitMaker => "LIMIT_MAKER".to_string(),
        }
    }
}

/// 订单有效期（字符串版本，用于API调用）
impl ToString for TimeInForce {
    fn to_string(&self) -> String {
        match self {
            TimeInForce::Gtc => "GTC".to_string(),
            TimeInForce::Ioc => "IOC".to_string(),
            TimeInForce::Fok => "FOK".to_string(),
            TimeInForce::Gtx => "GTX".to_string(),
        }
    }
}

/// 订单响应类型（字符串版本，用于API调用）
impl ToString for OrderResponseType {
    fn to_string(&self) -> String {
        match self {
            OrderResponseType::Ack => "ACK".to_string(),
            OrderResponseType::Result => "RESULT".to_string(),
            OrderResponseType::Full => "FULL".to_string(),
        }
    }
}

/// 订单请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderRequest {
    pub symbol: String,
    pub side: OrderSide,
    pub order_type: OrderType,
    pub time_in_force: Option<TimeInForce>,
    pub quantity: Option<Decimal>,
    pub quote_order_qty: Option<Decimal>,
    pub price: Option<Decimal>,
    pub new_client_order_id: Option<String>,
    pub stop_price: Option<Decimal>,
    pub iceberg_qty: Option<Decimal>,
    pub new_order_resp_type: Option<OrderResponseType>,
    pub recv_window: Option<u64>,
}

/// 订单响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderResponse {
    pub symbol: String,
    pub order_id: u64,
    pub client_order_id: String,
    pub price: Decimal,
    pub orig_qty: Decimal,
    pub executed_qty: Decimal,
    pub cummulative_quote_qty: Decimal,
    pub status: OrderStatus,
    pub time_in_force: TimeInForce,
    pub order_type: OrderType,
    pub side: OrderSide,
    pub stop_price: Option<Decimal>,
    pub iceberg_qty: Option<Decimal>,
    pub time: u64,
    pub update_time: u64,
    pub is_working: bool,
    pub orig_quote_order_qty: Decimal,
}

/// 取消订单响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CancelOrderResponse {
    pub symbol: String,
    pub order_id: u64,
    pub client_order_id: String,
    pub price: Decimal,
    pub orig_qty: Decimal,
    pub executed_qty: Decimal,
    pub cummulative_quote_qty: Decimal,
    pub status: OrderStatus,
    pub time_in_force: TimeInForce,
    pub order_type: OrderType,
    pub side: OrderSide,
    pub stop_price: Option<Decimal>,
    pub iceberg_qty: Option<Decimal>,
    pub time: u64,
    pub update_time: u64,
    pub is_working: bool,
    pub orig_quote_order_qty: Decimal,
}

/// 账户信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountInfo {
    // 现货API字段
    #[serde(default)]
    pub maker_commission: i32,
    #[serde(default)]
    pub taker_commission: i32,
    #[serde(default)]
    pub buyer_commission: i32,
    #[serde(default)]
    pub seller_commission: i32,
    #[serde(default)]
    pub can_trade: bool,
    #[serde(default)]
    pub can_withdraw: bool,
    #[serde(default)]
    pub can_deposit: bool,
    #[serde(default)]
    pub update_time: u64,
    #[serde(default)]
    pub account_type: String,
    #[serde(default)]
    pub balances: Vec<Balance>,
    #[serde(default)]
    pub permissions: Vec<String>,
    
    // 期货API字段
    #[serde(default)]
    pub total_initial_margin: Decimal,
    #[serde(default)]
    pub total_maint_margin: Decimal,
    #[serde(default)]
    pub total_wallet_balance: Decimal,
    #[serde(default)]
    pub total_unrealized_profit: Decimal,
    #[serde(default)]
    pub total_margin_balance: Decimal,
    #[serde(default)]
    pub total_position_initial_margin: Decimal,
    #[serde(default)]
    pub total_open_order_initial_margin: Decimal,
    #[serde(default)]
    pub total_cross_wallet_balance: Decimal,
    #[serde(default)]
    pub total_cross_un_pnl: Decimal,
    #[serde(default)]
    pub available_balance: Decimal,
    #[serde(default)]
    pub max_withdraw_amount: Decimal,
    #[serde(default)]
    pub assets: Vec<FuturesAsset>,
    #[serde(default)]
    pub positions: Vec<FuturesPosition>,
}

/// 余额
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Balance {
    pub asset: String,
    pub free: Decimal,
    pub locked: Decimal,
}

/// 期货资产
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FuturesAsset {
    pub asset: String,
    #[serde(rename = "walletBalance")]
    pub wallet_balance: Decimal,
    #[serde(rename = "unrealizedProfit")]
    pub unrealized_profit: Decimal,
    #[serde(rename = "marginBalance")]
    pub margin_balance: Decimal,
    #[serde(rename = "maintMargin")]
    pub maint_margin: Decimal,
    #[serde(rename = "initialMargin")]
    pub initial_margin: Decimal,
    #[serde(rename = "positionInitialMargin")]
    pub position_initial_margin: Decimal,
    #[serde(rename = "openOrderInitialMargin")]
    pub open_order_initial_margin: Decimal,
    #[serde(rename = "crossWalletBalance")]
    pub cross_wallet_balance: Decimal,
    #[serde(rename = "crossUnPnl")]
    pub cross_un_pnl: Decimal,
    #[serde(rename = "availableBalance")]
    pub available_balance: Decimal,
    #[serde(rename = "maxWithdrawAmount")]
    pub max_withdraw_amount: Decimal,
    #[serde(rename = "updateTime")]
    pub update_time: u64,
}

/// 期货持仓
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FuturesPosition {
    pub symbol: String,
    #[serde(rename = "positionSide")]
    pub position_side: String,
    #[serde(rename = "positionAmt", default)]
    pub position_amt: Decimal,
    #[serde(rename = "unrealizedProfit", default)]
    pub unrealized_profit: Decimal,
    #[serde(rename = "isolatedMargin", default)]
    pub isolated_margin: Decimal,
    #[serde(default)]
    pub notional: Decimal,
    #[serde(rename = "isolatedWallet", default)]
    pub isolated_wallet: Decimal,
    #[serde(rename = "initialMargin", default)]
    pub initial_margin: Decimal,
    #[serde(rename = "maintMargin", default)]
    pub maint_margin: Decimal,
    #[serde(rename = "updateTime", default)]
    pub update_time: u64,
}

/// 持仓
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Position {
    pub symbol: String,
    pub initial_margin: Decimal,
    pub maint_margin: Decimal,
    pub unrealized_pnl: Decimal,
    pub position_initial_margin: Decimal,
    pub open_order_initial_margin: Decimal,
    pub leverage: Decimal,
    pub isolated: bool,
    pub entry_price: Decimal,
    pub max_notional: Decimal,
    pub bid_notional: Decimal,
    pub ask_notional: Decimal,
    pub position_side: PositionSide,
    pub position_amt: Decimal,
    pub update_time: u64,
}

/// 交易记录
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trade {
    pub symbol: String,
    pub id: u64,
    pub order_id: u64,
    pub order_list_id: i64,
    pub price: Decimal,
    pub qty: Decimal,
    pub quote_qty: Decimal,
    pub commission: Decimal,
    pub commission_asset: String,
    pub time: u64,
    pub is_buyer: bool,
    pub is_maker: bool,
    pub is_best_match: bool,
}

/// 账户交易记录
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountTrade {
    pub symbol: String,
    pub id: u64,
    pub order_id: u64,
    pub order_list_id: i64,
    pub price: Decimal,
    pub qty: Decimal,
    pub quote_qty: Decimal,
    pub commission: Decimal,
    pub commission_asset: String,
    pub time: u64,
    pub is_buyer: bool,
    pub is_maker: bool,
    pub is_best_match: bool,
}

/// K线数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Kline {
    pub open_time: u64,
    pub open: Decimal,
    pub high: Decimal,
    pub low: Decimal,
    pub close: Decimal,
    pub volume: Decimal,
    pub close_time: u64,
    pub quote_asset_volume: Decimal,
    pub number_of_trades: u64,
    pub taker_buy_base_asset_volume: Decimal,
    pub taker_buy_quote_asset_volume: Decimal,
    pub ignore: Decimal,
}

/// 24小时价格变动统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Ticker {
    pub symbol: String,
    pub price_change: Decimal,
    pub price_change_percent: Decimal,
    pub weighted_avg_price: Decimal,
    pub prev_close_price: Decimal,
    pub last_price: Decimal,
    pub last_qty: Decimal,
    pub bid_price: Decimal,
    pub bid_qty: Decimal,
    pub ask_price: Decimal,
    pub ask_qty: Decimal,
    pub open_price: Decimal,
    pub high_price: Decimal,
    pub low_price: Decimal,
    pub volume: Decimal,
    pub quote_volume: Decimal,
    pub open_time: u64,
    pub close_time: u64,
    pub first_id: u64,
    pub last_id: u64,
    pub count: u64,
}

/// 订单簿
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderBook {
    pub last_update_id: u64,
    pub bids: Vec<(Decimal, Decimal)>,
    pub asks: Vec<(Decimal, Decimal)>,
}

/// 交易所信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExchangeInfo {
    pub timezone: String,
    #[serde(rename = "serverTime")]
    pub server_time: u64,
    #[serde(rename = "rateLimits")]
    pub rate_limits: Vec<RateLimit>,
    #[serde(rename = "exchangeFilters")]
    pub exchange_filters: Vec<serde_json::Value>,
    pub symbols: Vec<SymbolInfo>,
}

/// 速率限制
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RateLimit {
    #[serde(rename = "rateLimitType")]
    pub rate_limit_type: String,
    pub interval: String,
    #[serde(rename = "intervalNum")]
    pub interval_num: u32,
    pub limit: u32,
}

/// 交易对信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SymbolInfo {
    pub symbol: String,
    #[serde(default)]
    pub status: String,
    #[serde(rename = "baseAsset")]
    pub base_asset: String,
    #[serde(rename = "baseAssetPrecision")]
    pub base_asset_precision: u32,
    #[serde(rename = "quoteAsset")]
    pub quote_asset: String,
    #[serde(rename = "quotePrecision")]
    pub quote_precision: u32,
    #[serde(rename = "orderTypes")]
    pub order_types: Vec<String>,
    #[serde(rename = "icebergAllowed", default)]
    pub iceberg_allowed: bool,
    #[serde(rename = "ocoAllowed", default)]
    pub oco_allowed: bool,
    #[serde(rename = "isSpotTradingAllowed", default)]
    pub is_spot_trading_allowed: bool,
    #[serde(rename = "isMarginTradingAllowed", default)]
    pub is_margin_trading_allowed: bool,
    pub filters: Vec<serde_json::Value>,
    #[serde(default)]
    pub permissions: Vec<String>,
}

/// 24小时价格变动统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Ticker24hr {
    pub symbol: String,
    #[serde(rename = "priceChange", deserialize_with = "deserialize_decimal_or_string")]
    pub price_change: Decimal,
    #[serde(rename = "priceChangePercent", deserialize_with = "deserialize_decimal_or_string")]
    pub price_change_percent: Decimal,
    #[serde(rename = "weightedAvgPrice", deserialize_with = "deserialize_decimal_or_string")]
    pub weighted_avg_price: Decimal,
    #[serde(rename = "prevClosePrice", default)]
    pub prev_close_price: Decimal,
    #[serde(rename = "lastPrice", deserialize_with = "deserialize_decimal_or_string")]
    pub last_price: Decimal,
    #[serde(rename = "lastQty", deserialize_with = "deserialize_decimal_or_string", default)]
    pub last_qty: Decimal,
    #[serde(rename = "bidPrice", default)]
    pub bid_price: Decimal,
    #[serde(rename = "bidQty", default)]
    pub bid_qty: Decimal,
    #[serde(rename = "askPrice", default)]
    pub ask_price: Decimal,
    #[serde(rename = "askQty", default)]
    pub ask_qty: Decimal,
    #[serde(rename = "openPrice", deserialize_with = "deserialize_decimal_or_string")]
    pub open_price: Decimal,
    #[serde(rename = "highPrice", deserialize_with = "deserialize_decimal_or_string")]
    pub high_price: Decimal,
    #[serde(rename = "lowPrice", deserialize_with = "deserialize_decimal_or_string")]
    pub low_price: Decimal,
    #[serde(deserialize_with = "deserialize_decimal_or_string")]
    pub volume: Decimal,
    #[serde(rename = "quoteVolume", deserialize_with = "deserialize_decimal_or_string", default)]
    pub quote_volume: Decimal,
    #[serde(rename = "baseVolume", deserialize_with = "deserialize_decimal_or_string", default)]
    pub base_volume: Decimal,
    #[serde(rename = "openTime")]
    pub open_time: u64,
    #[serde(rename = "closeTime")]
    pub close_time: u64,
    #[serde(rename = "firstId")]
    pub first_id: u64,
    #[serde(rename = "lastId")]
    pub last_id: u64,
    pub count: u64,
}

/// 价格信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PriceInfo {
    pub symbol: String,
    #[serde(deserialize_with = "deserialize_decimal_or_string")]
    pub price: Decimal,
}

/// 自定义反序列化函数，支持字符串或数字格式的Decimal
fn deserialize_decimal_or_string<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
where
    D: serde::Deserializer<'de>,
{
    use serde::de::{self, Visitor};
    use std::fmt;
    use rust_decimal::prelude::FromPrimitive;

    struct DecimalVisitor;

    impl<'de> Visitor<'de> for DecimalVisitor {
        type Value = Decimal;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("a string or number representing a decimal")
        }

        fn visit_str<E>(self, value: &str) -> Result<Decimal, E>
        where
            E: de::Error,
        {
            value.parse().map_err(de::Error::custom)
        }

        fn visit_f64<E>(self, value: f64) -> Result<Decimal, E>
        where
            E: de::Error,
        {
            Decimal::from_f64(value).ok_or_else(|| de::Error::custom("Invalid decimal"))
        }

        fn visit_i64<E>(self, value: i64) -> Result<Decimal, E>
        where
            E: de::Error,
        {
            Decimal::from_i64(value).ok_or_else(|| de::Error::custom("Invalid decimal"))
        }

        fn visit_u64<E>(self, value: u64) -> Result<Decimal, E>
        where
            E: de::Error,
        {
            Decimal::from_u64(value).ok_or_else(|| de::Error::custom("Invalid decimal"))
        }
    }

    deserializer.deserialize_any(DecimalVisitor)
}

/// 订单簿价格
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BookTicker {
    pub symbol: String,
    pub bid_price: Decimal,
    pub bid_qty: Decimal,
    pub ask_price: Decimal,
    pub ask_qty: Decimal,
}

/// 聚合交易
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AggTrade {
    pub symbol: String,
    pub id: u64,
    pub price: Decimal,
    pub qty: Decimal,
    pub first_trade_id: u64,
    pub last_trade_id: u64,
    pub time: u64,
    pub is_buyer_maker: bool,
    pub is_best_match: bool,
}

/// 账户状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountStatus {
    pub msg: String,
    pub success: bool,
}

/// API交易状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiTradingStatus {
    pub data: TradingStatusData,
}

/// 交易状态数据
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TradingStatusData {
    pub is_locked: bool,
    pub planned_recover_time: u64,
    pub trigger_condition: TriggerCondition,
    pub indicators: Indicators,
    pub update_time: u64,
}

/// 触发条件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TriggerCondition {
    pub gcr: u32,
    pub ifo: u32,
    pub ufc: u32,
}

/// 指标
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Indicators {
    pub btc_dominance: u32,
    pub altcoin_index: u32,
}

/// API权限
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiPermissions {
    pub ip_restrict: bool,
    pub create_time: u64,
    pub enable_withdrawals: bool,
    pub enable_internal_transfer: bool,
    pub permits_universal_transfer: bool,
    pub enable_vanilla_options: bool,
    pub enable_reading: bool,
    pub enable_futures: bool,
    pub enable_margin: bool,
    pub enable_spot_and_margin_trading: bool,
}

/// 用户数据流
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserDataStream {
    pub listen_key: String,
}

/// 订单信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OrderInfo {
    pub symbol: String,
    pub order_id: u64,
    pub client_order_id: String,
    pub price: Decimal,
    pub orig_qty: Decimal,
    pub executed_qty: Decimal,
    pub cummulative_quote_qty: Decimal,
    pub status: OrderStatus,
    pub time_in_force: TimeInForce,
    pub order_type: OrderType,
    pub side: OrderSide,
    pub stop_price: Option<Decimal>,
    pub iceberg_qty: Option<Decimal>,
    pub time: u64,
    pub update_time: u64,
    pub is_working: bool,
    pub orig_quote_order_qty: Decimal,
}
